/*
 Copyright (c) 2011 LIX, Ecole Polytechnique, Palaiseau, France

 Title: hazmat variator
 Description: variator for the problem of routing hazardous material in a graph
 Copyright: Copyright (c) 2011
 Company: Ecole Polytechnique
 Authors: Nora Touati-Moungla and Dimo Brockhoff, Ecole Polytechnique, France
 Authors (previous Java version): Tamara Ulrich, ETH Zurich, Switzerland
 */


/** Contains the methods which are called in the different states of the <code>StateMachine</code>.
 * It includes two methods for state 0 and state 2, as well as methods for reading the parameter and
 * configuration files.
 *
 * @author Tamara Ulrich
 * @version 1.0
 */

#include <string>
#include <exception>

#include "Variator.h"
#include "States.h"

using namespace std;

	/** Initializes the variator. The parameters are read and tested for reasonability, the population is initialized
	 * and the initial file and the first variator file is written.
	 */
	void States::state0(){
		readParam(Variator::population.paramFileName);
		readParam(Variator::population.configFile);
		Variator::population.testParam();

		Variator::randomGenerator.setSeed(Variator::population.seed);

		Variator::population.initialize();
		Variator::population.writePopulation(Variator::population.initialFile);
		Variator::population.writePopulation(Variator::population.variatorFile);

		Variator::debugPrint("Generation counter set to 1.");
		Variator::population.generation = 1;
	}

	/** The main state of the variator which performs the variation. It cleans the population by removing all individuals
	 * which are not contained in the archive file (which is generated by the selector). Then, it performs recombination and
	 * mutation on the parent individuals given by the selector file (which is also generated by the selector) and writes the offspring
	 * to the variator file.
	 */
	void States::state2(){
		Variator::population.generation += 1;
		Variator::population.performClean();
		Variator::debugPrint("Clean of population finished.");
		Variator::population.variate();
		Variator::debugPrint("Variation finished.");
		Variator::population.writePopulation(Variator::population.variatorFile, Variator::population.offspring);
	}

	/** Reads the parameters in the given file. Skips over empty lines and lines starting with a <code>#</code>.
	 *
	 * @param filename the name of the file which contains the parameters
	 */
	void States::readParam(string filename) {
		bool readCorrectly = true;
		try {
			ifstream myFile (filename.c_str());
			if (myFile.is_open()) {
				while ( myFile.good() ) {
					string paramName = "";
					string paramValue = "";
					string nextParam;
					getline (myFile, nextParam);

					/* continue with next line, if no key found */
					if (nextParam.length() == 0) {
						continue;
					}

					/* forget about comments */
					if (nextParam.at(0) == '#') {
						continue;
					}

					/* read next line, split it and extract name and value */
					string buf; // Have a buffer string
					stringstream ss(nextParam); // Insert the string into a stream
				    vector<string> tokens; // Create vector to hold our words
				    while (ss >> buf)
				    	tokens.push_back(buf);

					paramName = tokens.at(0);
					paramValue = tokens.at(1);

					// first, see if the parameter is a fixed parameter of the abstract PopulationAbstract class.
					// If this is not the case, see if it is a user-defined parameter in the Population class.
					if (!Variator::population.setFixedParam(paramName, paramValue)) {
						readCorrectly = readCorrectly && Variator::population.setNonfixedParam(paramName, paramValue);
					}
				}
			}
			myfile.close();
		}
		catch (exception& e) {
			cerr << "Problem reading the parameter file! Terminating!" << endl;
			cerr << e.what() << endl;
		}

		if (!readCorrectly){
			cerr << "Could not read parameter file." << endl;
			exit(1);
		}

	}


